import React from 'react';
import { Form, Select, Checkbox, Input } from 'antd';
import { UploadOssCompact } from '@/containers';
import { renderHiddenField, getLeafId, OFFICE_FILE_TYPES } from '@/utils/utils';
import styles from './Sever.less';

const Uploader = ({ type, data, form, isEdit, visible, formValueMap }) => {
    const { getFieldDecorator } = form;
    const { id } = data;

    const existFileList = formValueMap.scenes?.[type]?.scenesFileDisplay?.[id];

    React.useEffect(() => {
        if (existFileList) {
            form.setFieldsValue({
                [`scenes[${type}]['scenesFileDisplay'][${id}]`]: existFileList
            });
        }
    }, [JSON.stringify(existFileList)]);

    return (
        <>
            <Form.Item
                label={isEdit ? '附件证明' : ' '}
                extra={isEdit && '支持图片、办公文件等多种格式，单个文件大小100M以内，最多上传10个'}
                required={visible && isEdit}
                colon={isEdit}
                className={!isEdit && styles.hackLabel}
            >
                {getFieldDecorator(`scenes[${type}]['scenesFileDisplay'][${id}]`)(
                    <UploadOssCompact
                        rules={[{ max: 100 }, { length: 10 }, { type: OFFICE_FILE_TYPES }]}
                        editable={isEdit}
                        onResourceChange={resource => {
                            form.setFieldsValue({
                                [`scenes[${type}]['files'][${id}]`]: resource ? [resource] : null
                            });
                            setTimeout(() => {
                                form.validateFields([`scenes[${type}]['applySceneId']`]);
                            });
                        }}
                        ossType="private"
                        categoryCode="DimissionSceneProveFile"
                    />
                )}
            </Form.Item>
            <Form.Item style={{ display: 'none' }}>
                {getFieldDecorator(`scenes[${type}]['files'][${id}]`)(<Input />)}
            </Form.Item>
        </>
    );
};

const Relative = ({ type, data, form, rules, visible, isEdit, formValueMap, renderItem }) => {
    const { getFieldDecorator } = form;
    const { id } = data;

    const initialValue = formValueMap.scenes[type]?.ruleCorrelationIds[id] ?? [];

    const editContent = (
        <Form.Item label="制度关联" required={visible && isEdit} className={styles.hack}>
            {getFieldDecorator(`scenes[${type}]['ruleCorrelationIds'][${id}]`)(
                <Select
                    mode="multiple"
                    placeholder="请选择关联制度"
                    style={{ width: 240 }}
                    onChange={() => {
                        setTimeout(() => {
                            form.validateFields([`scenes[${type}]['applySceneId']`]);
                        });
                    }}
                >
                    {rules.map(item => {
                        const key = `${type}-${id}-${item.id}`;
                        return (
                            <Select.Option key={key} value={key}>
                                {item.institutionName}
                            </Select.Option>
                        );
                    })}
                </Select>
            )}
        </Form.Item>
    );

    return isEdit ? (
        editContent
    ) : (
        <>
            {rules
                .filter(item => {
                    const key = `${type}-${id}-${item.id}`;
                    return initialValue.includes(key);
                })
                .map(item => {
                    const key = `${type}-${id}-${item.id}`;
                    return <span key={key}>{renderItem(item.institutionName)}</span>;
                })}
            {renderHiddenField({ form, field: `scenes[${type}]['ruleCorrelationIds'][${id}]`, initialValue })}
        </>
    );
};

const appendItemRender = value => value;

const Append = props => {
    const { data, type, filterType = [], prefix = '', renderItem = appendItemRender } = props;
    const appendAry = data.proofRequirementType.split(',');
    const map = {
        2: <Uploader {...props} />,
        3: <Relative {...props} renderItem={renderItem} />
    };
    const formatAppendAry = appendAry.sort().filter(item => (filterType.length ? filterType.includes(item) : true));
    return (
        <>
            {formatAppendAry.length ? prefix : null}
            {formatAppendAry.map(item => (
                <span key={`${type}-${data.id}-${item}`}>{map[String(item)]}</span>
            ))}
        </>
    );
};

const Setting = ({ setting, curSeverType, applySceneId, form, rules, isEdit, formValueMap, ...rest }) => (
    <div>
        <div>请至少选择一个符合的场景，可多选</div>
        <Checkbox.Group {...rest}>
            {setting.map(typeItem => {
                const type = typeItem?.severTypeInfo?.severType;
                const list = typeItem?.severLaborRelationDetailList ?? [];
                return (
                    <div
                        key={type}
                        style={{
                            display: type === curSeverType ? 'block' : 'none'
                        }}
                    >
                        {list.map(item => {
                            const visible = applySceneId.includes(`${type}-${item.id}`);
                            const appendProps = {
                                form,
                                type,
                                data: item,
                                rules,
                                isEdit,
                                visible,
                                formValueMap
                            };
                            const key = `${type}-${item.id}`;
                            return (
                                <div key={key} style={{ margin: '8px 0' }}>
                                    <Checkbox value={key}>{item.applyScene}</Checkbox>
                                    <div
                                        style={{
                                            display: visible ? 'block' : 'none'
                                        }}
                                    >
                                        <Append {...appendProps} />
                                    </div>
                                </div>
                            );
                        })}
                    </div>
                );
            })}
        </Checkbox.Group>
    </div>
);

const Sever = ({ form, setting = [], rules = [], curSeverType, isEdit, severType, formValueMap }) => {
    const { getFieldDecorator } = form;
    const keyForSceneId = `scenes[${severType}]['applySceneId']`;
    const applySceneId = form.getFieldValue(keyForSceneId) ?? formValueMap.scenes[severType]?.applySceneId ?? [];

    const settingProps = { setting, curSeverType, applySceneId, form, rules, isEdit, formValueMap };

    const isCurSeverType = curSeverType === severType;
    const curSetting = setting.find(typeItem => typeItem?.severTypeInfo?.severType === curSeverType) ?? {};

    // 1、不同的适用情形都要保存，就是说切换解除类型的时候，对应的适用情形下，数据要保存
    // 2、校验规则只生效于当前适用情形
    // 3、编辑态和浏览态不同的渲染方式
    // 以上3点结合antd3.x的form，各种反直觉的渲染/校验问题
    // 统一将错误收集放到父组件来做，但仍然很难维护
    const formRules = React.useMemo(() => {
        if (!isEdit || !isCurSeverType) {
            return [];
        }
        return [
            { required: true, message: '适用情形不能为空' },
            {
                validator(_, values, callback) {
                    setTimeout(() => {
                        const { severLaborRelationDetailList = [] } = curSetting;
                        const hasError = values.some(settingPath => {
                            const errorMsg = '勾选场景的证明文件/制度关联不能为空';
                            const settingId = getLeafId(settingPath);
                            const { proofRequirementType = '' } =
                                severLaborRelationDetailList.find(item => item.id === settingId) ?? {};
                            if (proofRequirementType.includes('2')) {
                                const files = form.getFieldValue(`scenes[${severType}]['files'][${settingId}]`);
                                if (!files?.length) {
                                    callback(errorMsg);
                                    return true;
                                }
                            }
                            if (proofRequirementType.includes('3')) {
                                const rulesId = form.getFieldValue(
                                    `scenes[${severType}]['ruleCorrelationIds'][${settingId}]`
                                );
                                if (!rulesId?.length) {
                                    callback(errorMsg);
                                    return true;
                                }
                            }
                            return false;
                        });

                        if (!hasError) callback();
                    });
                }
            }
        ];
    }, [isEdit, isCurSeverType, form, curSetting]);

    return (
        <div>
            <Form.Item label="适用情形">
                {isEdit ? (
                    getFieldDecorator(keyForSceneId, {
                        initialValue: applySceneId,
                        rules: formRules
                    })(<Setting {...settingProps} />)
                ) : (
                    <>
                        {setting.map(typeItem => {
                            const type = typeItem?.severTypeInfo?.severType;
                            const list = typeItem?.severLaborRelationDetailList ?? [];
                            if (type !== curSeverType) return null;

                            return (
                                <div key={type}>
                                    {list.map((item, index) => {
                                        const visible = applySceneId.includes(`${type}-${item.id}`);
                                        if (!visible) return null;

                                        const appendProps = {
                                            form,
                                            type,
                                            data: item,
                                            rules,
                                            isEdit,
                                            visible,
                                            formValueMap
                                        };

                                        return (
                                            <div key={`${item.id}`}>
                                                <div>
                                                    {index + 1}.{item.applyScene}
                                                    <Append
                                                        {...appendProps}
                                                        filterType={['3']}
                                                        prefix="："
                                                        renderItem={value => <>《{value}》</>}
                                                    />
                                                </div>
                                                <Append {...appendProps} filterType={['2']} />
                                            </div>
                                        );
                                    })}
                                </div>
                            );
                        })}
                        {renderHiddenField({
                            field: keyForSceneId,
                            initialValue: applySceneId,
                            form
                        })}
                    </>
                )}
            </Form.Item>
        </div>
    );
};

export default Sever;
